package com.example.config;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * springboot使用aop配置
 */
@Component
@Aspect
public class WebControllerAop {
    //controller包及其子包下的所有类的所有方法
    @Pointcut("execution(* com.example.controller.*.*(..))")
    public void executeService() {
        System.out.println("哈哈哈哈");
    }

    /**
     * 前置通知，方法调用前被调用
     *
     * @param joinPoint
     */
    /**
     * 方法执行之前获取方法参数
     *
     * @param joinPoint
     */
    @Before("executeService()")
    public void doBeforeAdvice(JoinPoint joinPoint) {
        System.out.println("我是前置通知!!!");
        //获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();
        //AOP代理类的信息
        joinPoint.getThis();
        //代理的目标对象
        joinPoint.getTarget();
        //用的最多 通知的签名
        Signature signature = joinPoint.getSignature();
        //代理的是哪一个方法
        // System.out.println(signature.getName());
        //AOP代理类的名字
        //System.out.println(signature.getDeclaringTypeName());
        //AOP代理类的类（class）信息
        signature.getDeclaringType();
        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //如果要获取Session信息的话，可以这样写：
        //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> parameterMap = new HashMap<>();
        while (enumeration.hasMoreElements()) {
            String parameter = enumeration.nextElement();
            parameterMap.put(parameter, request.getParameter(parameter));
        }
        String str = JSON.toJSONString(parameterMap);
        if (obj.length > 0) {
            System.out.println("请求的参数信息为：" + str);
        }
    }

    /**
     * 获取方法返回值，但无法改变方法返回值
     * 适合记录日志等操作
     *
     * @param joinPoint
     * @param obj
     */
    @AfterReturning(value = "executeService()", returning = "obj")
    public void doAfterAdvice(JoinPoint joinPoint, Object obj) {
        System.out.println("方法" + joinPoint.getSignature().getDeclaringTypeName()
                + "." + joinPoint.getSignature().getName() + "的返回值为：" + obj);
    }

    /**
     * 可以改变方法的返回值，但无法改变方法的返回值类型
     *
     * @param thisJoinPoint
     * @return
     */
    @Around("executeService()")
    public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint) {
        System.out.println("切面执行了。。。。");
        try {
            Object obj = thisJoinPoint.proceed();
            System.out.println(obj);
            obj = "你好，spring-boot!";
            System.out.println(obj);
            return obj;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }
}
